package com.sleepless.my.component;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import jakarta.websocket.*;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@ServerEndpoint(value = "/websocket/{username}")
@Slf4j
@Component
public class WebSocketServer {
    /**
     * 记录当前在线连接数
     */
    public static final Map<String, Session> sessionMap = new ConcurrentHashMap<>();
    public static final Map<String, HashSet<String>> roomMap = new ConcurrentHashMap<>();
    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username) {
        sessionMap.put(username, session);
        roomMap.computeIfAbsent("all", k -> new HashSet<>());
        roomMap.get("all").add(username);
        log.info("有新用户加入，username={}, 当前在线人数为：{}", username, sessionMap.size());
        sendOnlineUsers();
    }
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose(Session session, @PathParam("username") String username) {
        sessionMap.remove(username);
        roomMap.forEach((room, userList) -> userList.remove(username));
        roomMap.entrySet().removeIf(entry -> entry.getValue().isEmpty());
        log.info("有一连接关闭，移除username={}的用户session, 当前在线人数为：{}", username, sessionMap.size());
        sendOnlineUsers();
    }
    /**
     * 收到客户端消息后调用的方法
     * 后台收到客户端发送过来的消息
     * onMessage 是一个消息的中转站
     * 接受 浏览器端 socket.send 发送过来的 json数据
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, @PathParam("username") String username) {
        log.info("服务端收到用户username={}的消息:{}", username, message);
        JSONObject obj = JSONObject.parseObject(message);
        String to = obj.getString("to");
        String text = obj.getString("text");
        String type=obj.getString("type");
        // {"to": "admin", "text": "聊天文本"}
        switch (type){
            case "chat":
                sendChatMessage(to, username, text);
                break;
            case "room":
                sendRoomMessage(to, username, text);
                break;
            case "join":
                roomMap.get(to).add(username);
                break;
            case "exit":
                roomMap.get(to).remove(username);
                break;
            case "add":
                roomMap.computeIfAbsent(to, k -> new HashSet<>());
                break;
            case "del":
                roomMap.remove(to);
                break;
            default:
                break;
        }
    }
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("发生错误");
        error.printStackTrace();
    }
    /**
     * 服务端发送消息给客户端
     */
    private void sendMessage(String message, Session toSession) {
        try {
            log.info("服务端给客户端[{}]发送消息{}", toSession.getId(), message);
            toSession.getBasicRemote().sendText(message);
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }
    /**
     * 服务端发送消息给所有客户端
     */
    private void sendAllMessage(String message) {
        try {
            for (Session session : sessionMap.values()) {
                log.info("服务端给客户端[{}]发送消息{}", session.getId(), message);
                session.getBasicRemote().sendText(message);
            }
        } catch (Exception e) {
            log.error("服务端发送消息给客户端失败", e);
        }
    }

    private void sendOnlineUsers() {
        JSONObject result = new JSONObject();
        JSONArray array = new JSONArray();
        result.put("type", "online");
        result.put("users", array);
        for (Object key : sessionMap.keySet()) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("username", key);
            // {"username", "zhang", "username": "admin"}
            array.add(jsonObject);
        }
//        {"users": [{"username": "zhang"},{ "username": "admin"}]}
        sendAllMessage(JSONObject.toJSONString(result));  // 后台发送消息给所有的客户端
    }

    private void syncMessage() {

    }

    private void sendChatMessage(String to, String username, String text) {
        Session toSession = sessionMap.get(to);
        if (toSession == null) {
            log.error("发送消息失败");
            return;
        }
        JSONObject result = new JSONObject();
        result.put("from", username);
        result.put("text", text);
        result.put("type", "chat");
        sendMessage(result.toJSONString(), toSession);
    }

    private void sendRoomMessage(String to, String username, String text) {
        for (String s : roomMap.get(to)) {
            Session toSession = sessionMap.get(s);
            if (toSession == null) {
                log.error("发送消息失败");
                continue;
            }
            JSONObject result = new JSONObject();
            result.put("from", username);
            result.put("room", to);//roomID
            result.put("text", text);
            result.put("type", "room");
            sendMessage(result.toJSONString(), toSession);
        }
    }

}
